package dfl.bysj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import dfl.bysj.entity.*;
import dfl.bysj.entity.VO.*;
import dfl.bysj.exception.Assert;
import dfl.bysj.mapper.StudentSeatRelationMapper;
import dfl.bysj.result.ResponseEnum;
import dfl.bysj.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author DFL
 * @since 2022-04-26
 */
@Slf4j
@Service
public class StudentSeatRelationServiceImpl extends ServiceImpl<StudentSeatRelationMapper, StudentSeatRelation> implements StudentSeatRelationService {

    private SeatStateService seatStateService;

    private StudentSeatRelationMapper studentSeatRelationMapper;

    private HonestStudentService honestStudentService;

    private UserTeacherStudentService userTeacherStudentService;

    private HonestGradeService honestGradeService;

    private RedisTemplate redisTemplate;

    private StudentService studentService;

    @Autowired
    public UserTeacherStudentService getUserTeacherStudentService() {
        return userTeacherStudentService;
    }

    @Autowired
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    @Autowired
    public void setHonestGradeService(HonestGradeService honestGradeService) {
        this.honestGradeService = honestGradeService;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setUserTeacherStudentService(UserTeacherStudentService userTeacherStudentService) {
        this.userTeacherStudentService = userTeacherStudentService;
    }

    @Autowired
    public void setHonestStudentService(HonestStudentService honestStudentService) {
        this.honestStudentService = honestStudentService;
    }

    @Autowired
    public void setStudentSeatRelationMapper(StudentSeatRelationMapper studentSeatRelationMapper) {
        this.studentSeatRelationMapper = studentSeatRelationMapper;
    }

    @Autowired
    public void setSeatStateService(SeatStateService seatStateService) {
        this.seatStateService = seatStateService;
    }

    /**
     * 预约：
     * 1.1：先检查是否已有预约,通过检查是否有未过期的预约
     * 1、修改seat_state表的预约状态
     * 2、插入预约表
     * 3、需要返回成功预约的座位相关内容
     *
     * @param reserveVO
     */
    @Override
    public ReserveSUCCVO reserve(ReserveVO reserveVO) {

        UserTeacherStudent userTeacherStudent = userTeacherStudentService.getOne(
                new QueryWrapper<UserTeacherStudent>()
                        .eq("stu_id", reserveVO.getStuId())
                        .eq("check_state", 1));

//        //检查是否已有其他预约
//        StudentSeatRelation check = studentSeatRelationMapper.selectOne(new QueryWrapper<StudentSeatRelation>()
//                .eq("stu_use_id", userTeacherStudent.getStuUseId())
//                .eq("overtime_check", false));
//        Assert.isNull(check, ResponseEnum.RESERVE_EXISTED);

        //修改座位状态
        SeatState seatState = new SeatState();
        seatState.setResStaId(2);
        seatStateService.update(seatState,
                new QueryWrapper<SeatState>()
                        .eq("sea_sta_id", Integer.parseInt(reserveVO.getSeaStaId()))
                        .eq("res_time_id", reserveVO.getResTimeId()));

        LocalDateTime start = converToLocalDateTime(reserveVO.getStartTime());
        LocalDateTime end = converToLocalDateTime(reserveVO.getEndTime());
//        log.info(start+"::::"+end);
        StudentSeatRelation studentSeatRelation = new StudentSeatRelation();
        studentSeatRelation.setSeaStaId(Integer.parseInt(reserveVO.getSeaStaId()));
        studentSeatRelation.setStuUseId(userTeacherStudent.getStuUseId());
        studentSeatRelation.setSignState(false);
        studentSeatRelation.setSingBackState(false);
        studentSeatRelation.setResStartTime(start);
        studentSeatRelation.setResEndTime(end);
        studentSeatRelation.setOvertimeCheck(false);
        studentSeatRelationMapper.insert(studentSeatRelation);

        return ReserveSUCCVO
                .getReserveSUCCVO(studentSeatRelationMapper
                        .selectOne(new QueryWrapper<StudentSeatRelation>()
                                .eq("stu_use_id", userTeacherStudent.getStuUseId())
                                .eq("sea_sta_id", Integer.parseInt(reserveVO.getSeaStaId()))
                                .eq("overtime_check", false)));


    }

    @Override
    public StudentSeatRelation getStudentSeatRealation(Integer stuUseId, boolean b) {
        return studentSeatRelationMapper.selectOne(
                new QueryWrapper<StudentSeatRelation>()
                        .eq("stu_use_id", stuUseId)
                        .eq("overtime_check", b)
        );
    }

    /**
     * 登录检查：
     * 签到时间已过
     * 1、修改预约状态
     * 2、信用违规加记录
     * 3、修改信用分
     */
    @Override
    public HonestGrade signLost(StudentSeatRelation s) {
        StudentSeatRelation studentSeatRelation = new StudentSeatRelation();
        studentSeatRelation.setOvertimeCheck(true);
        update(studentSeatRelation, new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", s.getStuSeaId())
                .eq("overtime_check", false));

        //注意：查一下有没有其他人预约这个座位而且还未过期的
        updateSeaState_ResState(s.getSeaStaId());


        return honestStudentService.insertHonestStudent(s.getSeaStaId(), 2);

    }

    /**
     * 检查并修改是否需要修改 座位状态
     *
     * @param seaStaId
     */
    private void updateSeaState_ResState(Integer seaStaId) {
        Boolean check = checkSeaState(seaStaId);
        if (check) {
            SeatState seatState = new SeatState();
            seatState.setResStaId(1);
            seatStateService.update(seatState, new QueryWrapper<SeatState>()
                    .eq("sea_sta_id", seaStaId));
        }
    }

    private Boolean checkSeaState(Integer seaStaId) {
        List<StudentSeatRelation> studentSeatRelations = studentSeatRelationMapper.selectList
                (new QueryWrapper<StudentSeatRelation>()
                        .eq("sea_sta_id", seaStaId)
                        .eq("overtime_check", false)
                );
        if (studentSeatRelations.isEmpty()) {
            return true;
        }
        return false;
    }

    @Override
    public HonestGrade signBackLost(StudentSeatRelation s) {
        StudentSeatRelation studentSeatRelation = new StudentSeatRelation();
        studentSeatRelation.setOvertimeCheck(true);
        update(studentSeatRelation, new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", s.getStuSeaId()));

        updateSeaState_ResState(s.getSeaStaId());

        return honestStudentService.insertHonestStudent(s.getStuUseId(), 1);
    }

    /**
     * 获取日期为当天的所有 以及overtime为false
     *
     * @return
     */
    @Override
    public List<StudentSeatRelation> getRelationTodayAndOverTimeCheck() {

        log.info(getToday());
        return studentSeatRelationMapper.selectList(
                new QueryWrapper<StudentSeatRelation>()
                        .eq("overtime_check", false)
                        .like("res_start_time", getToday() + '%')
        );

    }

    @Override
    public ReserveSUCCVO getReserveSUCCByToken(Integer stuId) {
        UserTeacherStudent userTeacherStudent = userTeacherStudentService.getOne(
                new QueryWrapper<UserTeacherStudent>()
                        .eq("stu_id", stuId)
                        .eq("check_state", true));

        StudentSeatRelation studentSeatRelation = getOne(new QueryWrapper<StudentSeatRelation>()
                .eq("stu_use_id", userTeacherStudent.getStuUseId())
                .eq("overtime_check", false));

        if (studentSeatRelation == null) {
            return null;
        }
        return ReserveSUCCVO.getReserveSUCCVO(studentSeatRelation);
    }

    @Override
    public HonestGrade cancelSign(Integer stuSeaId, Integer stuUseId) {
        StudentSeatRelation studentSeatRelation = new StudentSeatRelation();
        studentSeatRelation = getOne(new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", stuSeaId));

        studentSeatRelation.setOvertimeCheck(true);
        update(studentSeatRelation, new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", stuSeaId)
                .eq("overtime_check", false));

        updateSeaState_ResState(studentSeatRelation.getSeaStaId());


        return honestStudentService.insertHonestStudent(stuUseId, 1);

    }

    @Override
    public void sign(String seaId, String stuSeaId) {
        //1、检查seaId与stuSeaId是不是同一个seat
        StudentSeatRelation studentSeatRelation = getOne(new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", stuSeaId));
        Assert.notNull(studentSeatRelation, ResponseEnum.NOT_RESERVE);

        SeatState seatState = seatStateService.getById(studentSeatRelation.getSeaStaId());
        Assert.isTrue(seatState.getSeaId().equals(Integer.parseInt(seaId)),
                ResponseEnum.SEAT_NOT_EQUAL);

        //2、相同：修改签到状态，如果还未过期的话
//        Assert.isTrue(!studentSeatRelation.getSignState(),ResponseEnum.HAS_SIGN);

        studentSeatRelation.setSignState(true);
        update(studentSeatRelation,
                new QueryWrapper<StudentSeatRelation>()
                        .eq("stu_sea_id", studentSeatRelation.getStuSeaId()));
    }

    @Override
    public void signback(String seaId, String stuSeaId) throws InterruptedException {
        //1、检查seaId与stuSeaId是不是同一个seat
        StudentSeatRelation studentSeatRelation = getOne(new QueryWrapper<StudentSeatRelation>()
                .eq("stu_sea_id", stuSeaId));
        Assert.notNull(studentSeatRelation, ResponseEnum.NOT_RESERVE);

        SeatState seatState = seatStateService.getById(studentSeatRelation.getSeaStaId());
        Assert.isTrue(seatState.getSeaId().equals(Integer.parseInt(seaId)),
                ResponseEnum.SEAT_NOT_EQUAL);

        //2、相同：修改签到状态，如果还未过期的话
//        Assert.isTrue(!studentSeatRelation.getSignState(),ResponseEnum.HAS_SIGN);

        Thread thread=new Thread(()-> {
            studentSeatRelation.setSingBackState(true);
            studentSeatRelation.setOvertimeCheck(true);
            update(studentSeatRelation,
                    new QueryWrapper<StudentSeatRelation>()
                            .eq("stu_sea_id", studentSeatRelation.getStuSeaId()));
        });
        thread.start();
        thread.join();
        updateSeaState_ResState(studentSeatRelation.getSeaStaId());


    }

    @Override
    public List<ReserveSUCCVO> getAllReserveSUCCByStuSeaId(String stuUseId) {
        List<StudentSeatRelation> studentSeatRelations = studentSeatRelationMapper.selectList(
                new QueryWrapper<StudentSeatRelation>()
                        .eq("stu_use_id", stuUseId)
        );

        List<ReserveSUCCVO> reserveSUCCVOS = new ArrayList<>();
        studentSeatRelations.stream()
                .forEach(s -> reserveSUCCVOS.add(ReserveSUCCVO.getReserveSUCCVO(s)));

        return reserveSUCCVOS;
    }

    @Override
    public List<SeatStudentDetailVO> getReserveSUCCBySeaStaId(String seaStaId, String resStartTime) {
        //获取对应座位的学生信息

       List<StudentSeatRelation>  studentSeatRelations = studentSeatRelationMapper.selectList(new QueryWrapper<StudentSeatRelation>()
                .eq("sea_sta_id", seaStaId)
                .eq("overtime_check", false)
                .like("res_start_time", resStartTime + "%"));
       List<SeatStudentDetailVO> seatStudentDetailVOS=new ArrayList<>();
       studentSeatRelations.stream()
               .forEach(s->{
                   SeatStudentDetailVO seatStudentDetailVO=new SeatStudentDetailVO();
                   seatStudentDetailVO.setReserveSUCCVO(ReserveSUCCVO.getReserveSUCCVO(s));

                   StudentVO student=userTeacherStudentService.getStudentVO(String.valueOf(s.getStuUseId()));
                   HonestGrade honestGrade=honestGradeService.getHonestGradeByStuUseId(s.getStuUseId());

                   seatStudentDetailVO.setHonestGrade(honestGrade);
                   seatStudentDetailVO.setStudent(student);

                   seatStudentDetailVOS.add(seatStudentDetailVO);
               });
        return seatStudentDetailVOS;

    }


    private String getToday() {
        LocalDateTime localDateTime = LocalDateTime.now();
        int year = localDateTime.getYear();
        Month month = localDateTime.getMonth();
        int mon = month.getValue();
        String mons;
        if (mon < 10) {
            mons = "0" + mon;
        } else {
            mons = String.valueOf(mon);
        }
        int day = localDateTime.getDayOfMonth();
        String days;
        if (day < 10) {
            days = "0" + day;
        } else {
            days = String.valueOf(day);
        }
        return String.valueOf(year) + '-' + mons + '-' + days;
    }

    private LocalDateTime converToLocalDateTime(String startTime) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm");
        return LocalDateTime.parse(startTime, dateTimeFormatter);
    }

    @Override
    public List<SeatStateVO> getALLSeatStateVO(Integer resTimeId) {
        List<SeatState> seatStates = seatStateService.list(
                new QueryWrapper<SeatState>()
                        .eq("res_time_id", resTimeId)
        );

        List<SeatStateVO> seatStateVOS = new ArrayList<>();

        seatStates.stream()
                .forEach(s -> seatStateVOS.add(new SeatStateVO(s)));

        seatStateVOS.stream()
                .filter(s -> s.getSeatState().getResStaId().equals(2))
                .forEach(s -> {
                    if (s != null) {
                        //sea_sta_id就约束了为今日
                        //要获取该sea_sta_id的座位关系
                        List<StudentSeatRelation> studentSeatRelations = studentSeatRelationMapper.selectList(
                                new QueryWrapper<StudentSeatRelation>()
                                        .eq("sea_sta_id", s.getSeatState().getSeaStaId())
                                        .eq("overtime_check", false)
                        );
                        if (studentSeatRelations != null) {
                            List<Map<String, String>> list = new ArrayList<>();
                            studentSeatRelations.stream()
                                    .forEach(a -> {
                                        Map<String, String> timeMap = new HashMap<>();
                                        timeMap.put("resStartTime", converStringTime(a.getResStartTime()));
                                        timeMap.put("resEndTime", converStringTime(a.getResEndTime()));
                                        list.add(timeMap);
                                    });
                            s.setTimeList(list);
                            //时间转换
                            log.info(s.toString());
                        }

                    }


                });

        return seatStateVOS;
    }

    @Override
    public List<ReserveSUCCVO> getAllReserveSUCCByStuId(int stuId) {
        //先查询到stuUseId
        UserTeacherStudent userTeacherStudent=  userTeacherStudentService.getOne(
                new QueryWrapper<UserTeacherStudent>()
                        .eq("stu_id", stuId)
                        .eq("check_state", true)
        );
        return getAllReserveSUCCByStuSeaId(String.valueOf(userTeacherStudent.getStuUseId()));
    }

    /**
     * 强制下座
     * @param stuUseId
     */
    @Override
    public void powerCancel(String stuUseId) throws InterruptedException {
        //1、修改座位状态

        StudentSeatRelation studentSeatRelation1= getOne(new QueryWrapper<StudentSeatRelation>()
                .eq("stu_use_id", stuUseId)
                .eq("overtime_check", false));

        if (studentSeatRelation1!=null){
            Thread thread=new Thread(()->{
                StudentSeatRelation studentSeatRelation=new StudentSeatRelation();
                studentSeatRelation.setOvertimeCheck(true);
                update(studentSeatRelation, new QueryWrapper<StudentSeatRelation>()
                        .eq("stu_use_id", stuUseId)
                        .eq("overtime_check", false));
            });
            thread.start();
            thread.join();
            updateSeaState_ResState(studentSeatRelation1.getSeaStaId());

        }
        honestStudentService.insertHonestStudent(Integer.valueOf(stuUseId), 3);
    }

    @Override
    public List<StudentSeatRelation> getAllSeatStateByStuUseId(QueryWrapper<StudentSeatRelation> eq) {
        return studentSeatRelationMapper.selectList(eq);
    }

    private String converStringTime(LocalDateTime localDateTime) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        return localDateTime.format(dateTimeFormatter);
    }
}
